package com.chengh.nami.core.security.service;

import com.chengh.nami.common.domain.model.LoginUserEntity;
import com.chengh.nami.common.domain.pojo.SysUser;
import com.chengh.nami.common.domain.pojo.SysRole;
import com.chengh.nami.common.domain.pojo.SysMenu;
import com.chengh.nami.common.utils.StringUtils;
import com.chengh.nami.system.service.ISysMenuService;
import com.chengh.nami.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * SpringSecurity用户的业务实现
 *
 * @author chengh
 */
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final ISysUserService userService;

    private final PasswordService passwordService;

    private final ISysMenuService sysMenuService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user = userService.getUserByName(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        passwordService.validate(user);
        // 获取用户的角色集合
        List<SysRole> roles = userService.getSysRoleByUserId(user.getId());
        // 获取用户的菜单集合
        List<SysMenu> menus = sysMenuService.getMenuByUserId(user.getId());
        // 获取用户所有的权限集合
        Set<String> permissions = getPermissions(menus);
        // 将用户的菜单转为树形结构,并且剔除按钮
        List<SysMenu> treeMenus = getTreeMenus(menus);
        return new LoginUserEntity(user.getId(), user.getUsername(), user.getPassword(), user.getDeptId(), user, roles, treeMenus, permissions);
    }

    private List<SysMenu> getTreeMenus(List<SysMenu> menus) {
        return menus.stream().filter(menu -> menu.getParentId() == 0).peek((menu) -> menu.setChildren(getChildren(menu, menus))).collect(Collectors.toList());
    }

    private Set<String> getPermissions(List<SysMenu> menus) {
        Set<String> permissions = new HashSet<>();
        if (!CollectionUtils.isEmpty(menus)) {
            for (SysMenu menu : menus) {
                if (StringUtils.isNotEmpty(menu.getPerms())) {
                    permissions.add(menu.getPerms());
                }
            }
        }
        return permissions;
    }

    /**
     * 递归获取子菜单
     *
     * @param menu  菜单列表
     * @param menus 最上级菜单
     * @return 菜单树
     */
    private List<SysMenu> getChildren(SysMenu menu, List<SysMenu> menus) {
        return menus.stream().filter(
                item -> item.getParentId().equals(menu.getId()) && ("0".equals(item.getMenuType()) || "1".equals(item.getMenuType()))
        ).peek(item -> item.setChildren(getChildren(item, menus))).collect(Collectors.toList());
    }
}
